﻿import com.mosesSupposes.fuse.FuseKitCommon;
import com.mosesSupposes.fuse.ZManager;

/**
* Fuse Kit 2
* Copyright (c) 2006 Moses Gunesch, MosesSupposes.com
* 
* Distributed under MIT Open Source License, see Fuse-Kit-License.html (in fuse package directory)
* Easing Equations (c) 2003 Robert Penner used by permission, see PennerEasing
* Visit http://www.mosessupposes.com/Fuse
*
* @ignore
*
* A robust central processing engine for all scripted tweens in a swf published to AS2.<br>
* <br>
* @usage
* Your project can be prepared to use ZigoEngine in these ways:
* <ul><li>Simply import this class and begin using static methods like {@link #doTween}.<br>
*  - You may then optionally extend the engine's capabilities using {@link #register}.<br></li>
* <li>Or, use {@link #simpleSetup} to add tweening shortcuts like <code>alphaTo</code> to MovieClips, Buttons and TextFields.</li></ul>
* <br>
* Extending prototypes is entirely optional in this version - all Shortcut functionality is excluded from the core engine class.<br><br>
* Events dispatched by ZigoEngine (see {@link #addListener} for more info):
* <ul>
* <li><code>onTweenAdd</code></li>
* <li><code>onTweenInterrupt</code></li>
* </ul>
* Events dispatched by individual target objects (see {@link com.mosesSupposes.fuse.ZManager} for more info):
* <ul><li><code>onTweenStart</code></li>
* <li><code>onTweenUpdate</code></li>
* <li><code>onTweenEnd</code></li></ul>
* 
* @author	Moses Gunesch / MosesSupposes.com / ZigoEngine based on concepts by Ladislav Zigo, Zeh Fernando
* @version	2.1.3r1
*/
class com.mosesSupposes.fuse.ZigoEngine {
	/**
	 * Enables kit version to be retrieved at runtime or when reviewing a decompiled swf. 
	 * @usage <pre>trace(ZigoEngine.VERSION); // if the version is incorrect, clear your ASO cache.</pre>
	 */
	public static var VERSION:String = FuseKitCommon.VERSION+', ZigoEngine based on concepts by L.Zigo';
	
	/**
	 * Default easing if unspecified.
	 * @usage <pre>// Example with a style from PennerEasing
	 * ZigoEngine.register(PennerEasing);
	 * ZigoEngine.EASING = 'easeInOutExpo';
	 * 
	 * // or - Alternate example with an mx style
	 * import mx.transitions.easing.Elastic;
	 * ZigoEngine.EASING = Elastic.easeOut;</pre>
	 * @description	This default is hardcoded in the engine and doesn't require that {@link com.mosesSupposes.fuse.PennerEasing} is registered. 
	 * However you will need to register that class with the engine if you wish to set this property to a similar string like "easeOutQuad". 
	 * You may also set this property to any standard easing function (like <code>mx.transitions.easing</code>).
	 */
	public static var EASING:Object = 'easeOutQuint';
	
	/**
	 * Default tween duration if unspecified.
	 * @usage <pre>// set once at beginning of program to change engine default setting.
	 * ZigoEngine.DURATION = .5;</pre>
	 * 
	 */
	public static var DURATION:Number = 1;
	
	/**
	 * Debug feature: Skips, speeds up, or slows all tweens globally. All time values in ZigoEngine and Fuse are multiplied by this number.
	 * @description	Affects all durations, delays, and time-based triggers kit-wide.
	 * <br><br>
	 * A reminder message like <code>[ ZigoEngine.TIME_MULTIPLIER: 20% ]</code> is sent to output each time the setting is changed, upon the start of the next tween 
	 * (unless ZigoEngine.OUTPUT_LEVEL has been set to 0). 
	 * <br><br>
	 * Set to 0 to fast-forward through all animation. Unlike {@link com.mosesSupposes.fuse.Fuse#fastForward}, all callbacks 
	 * and events associated with tweens are still fired, durations are simply set to 0. Note that based on {@link #SKIP_LEVEL} 
	 * settings this may alter some behaviors in your program.
	 * <br><br>
	 * Values between 0 and 1 cause tweens to run faster than their specified duration, on a percentage basis.
	 * For example a setting of .25 would reduce durations to 25% of their actual values, making tweens run 1-1/2 times faster.
	 * <br><br>
	 * Any value greater than 1 will cause tweens to run in slow motion by increasing durations on a percentage basis. 
	 * For example a setting of 2 would force tweens to run at half speed.
	 * @usage <pre>// set once at beginning of program to change engine default setting.
	 * ZigoEngine.TIME_MULTIPLIER = .5; // run all tweens at double-speed.</pre>
	 * <br>
	 * (advanced) Note that for more complex debugging of Fuse sequences you may want to set this property inline during the sequence. Example:
	 * <pre>var testMode:Boolean = true;
	 * function setTimeMultiplier(mult:Number):Void {
	 * 	if (testMode==true) ZigoEngine.TIME_MULTIPLIER = mult;
	 * }
	 * var f:Fuse = new Fuse();
	 * f.scope = this;
	 * // start sequence skipping through all tweens..
	 * f.push({ func:setTimeMultiplier, args:0 });
	 * // later in sequence return to normal speed..
	 * f.push({ func:setTimeMultiplier, args:1 });
	 * // etc.
	 * </pre>
	 */
	public static var TIME_MULTIPLIER:Number = 1;
	
	/**
	 * If set true the engine always rounds its math (helpful with pixelfonts).
	 * @usage <pre>// set once at beginning of program to change engine default setting.
	 * ZigoEngine.ROUND_RESULTS = true;</pre>
	 * @description	Degradation in animation and performance is minor with this feature enabled. Hence it was left a global toggle with the assumption that it should only be set true for projects requiring rounding.
	 */
	public static var ROUND_RESULTS:Boolean = false;
	
	/**
	* Controls how much feedback the engine outputs, helpful for debugging.
	* @usage <pre>ZigoEngine.OUTPUT_LEVEL = 2;<pre>
	* <ul>
	* 	<li>0 = no traces,</li> 
	*	<li>1 = normal errors & warnings</li>
	*	<li>2 = additional output</li>
	* </ul>
	*/
	public static var OUTPUT_LEVEL:Number = 1;
	
	/**
	 * (Legacy) Option to stop all tweening props in target as a new tween is added.
	 */ 
	public static var AUTOSTOP:Boolean = false; 
	
	/**
	 * (Advanced) Sets default engine behavior for situations where tweens fail to affect a visible change or have no duration.
	 * @usage <pre>// set once at beginning of program to change engine default setting.
	 * ZigoEngine.SKIP_LEVEL = 2;</pre>
	 * <b>No-duration tweens:</b><br>
	 * Tweens with a 0-second duration set the property immediately at the time of the tween call, or after any delay.<br>
	 * This behavior has advantages and disadvantages. It is <i>recommended</i> that you purposefully use 0-second tweens 
	 * to set properties that are handled by the engine at any time in your program, since this will 
	 * effectively stop any potentially running tweens on that property. (Trying to set a property while it is being tweened 
	 * usually has no effect.) However in some dynamic programs you may want tweens that end up having no duration to also
	 * skip their delay and/or callbacks and events - this can be controlled with SKIP_LEVEL.<br><br> 
	 * <b>No-change tweens:</b><br>
	 * Tweens at times end up being generated that affect no visual change. Normally the ZigoEngine operates under its 
	 * legacy behavior, which is to run such tweens regardless. This can be good (the program's sequence will continue 
	 * on a schedule) or bad (the tween is essentially invisible and will fire callbacks and events on update and end, 
	 * which may cause confusion). In some cases you may want to skip past tweens that don't do anything visually.<br>
	 * <br>
	 * The <code>SKIP_LEVEL</code> default, as well as the per-tween <code>skipLevel</code> parameter (see {@link #doTween}) 
	 * enable you to control the engine's behavior in these situations more accurately:
	 * <ul><li>0= Default.<br>No-change tweens are run with their full duration, delay, and callbacks/events. 
 	 * No-duration tweens set the property and execute all callbacks and events immediately or after a delay.</li>
	 * <li>1= Skip no-change tweens.<br>Tweens that affect no change are discarded (both delay and duration are ignored). Callbacks/events are fired immediately. No-duration tweens ignore delay and set properties immediately.</li>
	 * <li>2= Do not fire events or callbacks for no-change or no-duration tweens.<br>No-change tween calls are entirely ignored. No-duration tweens ignore delay and set properties immediately.</li></ul>
	 * <br>To review what property tweens were successfully added, {@link #doTween} returns a formatted list.
	 */
	public static var SKIP_LEVEL:Number = 0;
	
	/**
	 * A movieclip is created in the _root timeline to run the engine on an EnterFrame pulse.
	 * @description	Use {@link #setControllerDepth} to set the clip's level. By default it is set on depth 6789. A depth of 0 will be more convenient if you'll be using depth management in _root.
	 */ 
	private static var tweenHolder:MovieClip;
	
	/**
	 * Zmanager instance
	 * @description	Broken out to increase speed in as2
	 */
	private static var instance:ZManager;
	
	/**
	 * Internal setInterval id memory for ability to clearInterval
	 */
	private static var updateIntId:Number;
	
	/**
	 * Internal setting for running the engine on a setInterval pulse.
	 * @see	#setUpdateInterval
	 */
	private static var updateTime:Number;
	
	/**
	 * Internal boolean playing switch
	 */
	private static var _playing:Boolean = false;
	
	/**
	 * Internal counter for hidden __zigoID__ parameter written into target objects
	 */
	private static var zigoIDs:Number = 0;
	
	/**
	 * Internal table for externally registered classes which are stored via their registryKey string.
	 */
	private static var extensions:Object;
	
	/**
	 * Internal memory to detect change to TIME_MULTIPLIER
	 */
	private static var prevTimeMult:Number = 1;
	
	/**
	* Do not use constructor. All methods of engine are static.
	*/
	private function ZigoEngine(){} 
	
	/**
	 * Written by AsBroadcaster
	 * @ignore
	 * (Advanced) Use this method to add a listener for "onTweenAdd" and "onTweenInterrupt" events, 
	 * which are broadcast directly by the engine.
	 * @usage	These events are special in that they are dispatched directly by the ZigoEngine class, 
	 * unlike target-events such as <code>onTweenEnd</code> (see: {@link com.mosesSupposes.fuse.ZManager} 
	 * for more info). 
	 * <br><br>
	 * The "onTweenAdd" event is fired when any doTween call is made, and passes the final parameters 
	 * that will be sent to the internal ZManager instance in the following order:
	 * <ul>
	 * <li>An array of tween targets</li>
	 * <li>An array of property strings generated by the <code>ZManager.paramsObj</code> method.
	 * <br>Note: _scale and _size are split into movieclip properties, and duplicate properties 
	 * are stripped, with the exception of overlapping _fade / _alpha and overlapping color-transform tweens.</li>
	 * <li>A corresponding array of tween end-values for each validated property</li>
	 * <li>A validated numerical tween duration in seconds</li>
	 * <li>A valid easing function</li>
	 * <li>A validated numerical delay in seconds</li>
	 * <li>A specially-formatted and validated callback object generated by the <code>FuseKitCommon.parseCallback</code> method.</li>
	 * </ul>
	 * <pre>var myListener:Object = {
	 *     onTweenAdd:function(targets:Array, props:Array, endvals:Array, 
	 *                         seconds:Number, ease:Function, 
	 *                         delay:Number, callback:Object):Void {
	 *         trace("ZigoEngine is adding a tween:");
	 *         trace(" -targets:"+targets.join(","));
	 *         trace(" -props:"+props.join(","));
	 *         trace(" -endvals:"+endvals.join(","));
	 *         trace(" -seconds:"+seconds);
	 *         // (easing function is never undefined)
	 *         trace(" -delay:"+delay);
	 *         trace(" -has callback:"+Boolean(callback.start.f!=null 
	 *                                         || callback.upd.f!=null 
	 *                                         || callback.end.f!=null));
	 *     }
	 * };
	 * ZigoEngine.addListener(myListener);</pre>
	 * <br>
	 * The "onTweenInterrupt" event is fired in the following situations, and passes several additional parameters 
	 * including "during" which can provide a clue as to which situation caused the interruption.
	 * <ul>
	 * <li>Another tween call overwrote one or more property tweens in progress. during = "add".</li>
	 * <li>A <code>removeTween</code> call stopped one or more tweens in progress. during = "remove".</li>
	 * <li>A target goes missing, for instance if a MovieClip was removed during a tween, or a target is 
	 * deinitialized from the engine before its tweens complete. during = "update".</li>
	 * </ul>
	 * This ensures the event is fired even when targets go missing and are thus unable to dispatch the event. 
	 * To aid in tracking targets in that situation, the internal <code>__zigoID__</code> property for each target is also passed 
	 * in the event object. Any initialized/tweening target contains this read-only property, making it possible to advance-query 
	 * then later identify targets after they're removed. Missing targets can be further identified by the "target" parameter of 
	 * the event object (normally a reference to the actual tween target), which will be sent as a string like <code>[MISSING:"clip1_mc"]</code>.
	 * <pre>var myListener:Object = {
	 * 	onTweenInterrupt:function(o:Object):Void {
	 * 		trace("Interruption detected:");
	 * 		trace(" -during cycle:"+o.during);
	 * 		trace(" -target:"+o.target);
	 * 		trace(" -target id:"+o.__zigoID__);
	 * 		trace(" -properties interrupted:"+(o.props).toString());
	 * 	}
	 * };
	 * ZigoEngine.addListener(myListener);
	 * ZigoEngine.doTween(my_mc,"_alpha",0,2);
	 * 
	 * // click the mouse during the tween to receive the event.
	 * function onMouseDown():Void {
	 * 	my_mc.removeMovieClip();
	 * }</pre>
	 * @param the function or object that should be called
	 */
	public static function addListener(handler:Object):Void
	{
		AsBroadcaster.initialize(ZigoEngine);
		ZigoEngine.addListener(handler);
	}
	
	/**
	 * Written by AsBroadcaster
	 * @ignore
	 * Remove a listener for onTweenAdd or onTweenInterrupt events.
	 * @param the function or object that should be called
	 */
	public static function removeListener(handler:Object):Void {}
	
	/**
	* Returns true if the engine contains tweens and is running updates on a pulse
	*/
	public static function isPlaying():Boolean
	{
		return _playing;
	}
	
	/**
	* An alternative setup command that extends prototypes with shortcuts like <code>alphaTo</code>.
	* @description	This setup command should only be called once at the beginning of your program. 
	* Use either this or {@link #register}, not both. 
	* The difference is that <code>simpleSetup</code> alters base prototypes so that you may call tween methods 
	* directly on targets, such as <code>my_mc.alphaTo(0);</code>.<br><br>Example:
	* <pre>import com.mosesSupposes.fuse.*;
	* ZigoEngine.simpleSetup(Shortcuts,PennerEasing);</pre>
	* Note that to keep filesize to a minimum you should only register the features you intend to use. Use publish settings to "omit trace actions" to further reduce filesize.
	* @param	shortcutsClass <b>It is madadory to pass the {@link #Shortcuts} class during this call!</b> You may additionally pass any of the following classes (all are optional), as in the way PennerEasing is added above.
	* <li><code>PennerEasing</code> Enables shortcut strings like "easeOutQuad" to be used with the engine. See {@link com.mosesSupposes.fuse.PennerEasing}</li>
	* <li><code>Fuse</code> Enables Fuse for animation sequencing. Note that if animation won't be sequenced you do may simply import and use Fuse without ZigoEngine. See {@link com.mosesSupposes.fuse.Fuse}</li>
	* <li><code>FuseFMP</code> Enables shortcut strings like <code>DropShadow_distance</code> to be tweened in the engine. See {@link com.mosesSupposes.fuse.FuseFMP}</li>
	* <li><code>FuseItem</code> Enables Fuse-style Object Syntax to be used with the <code>ZigoEngine.doTween</code>. Note that Fuse does not need to be registered to use this feature. See {@link com.mosesSupposes.fuse.FuseItem}</li></ul>
	*/ 
	public static function simpleSetup(shortcutsClass:Function):Void
	{
		if (arguments.length>0) register.apply(ZigoEngine,arguments);
		_global.ZigoEngine = ZigoEngine; // This allows you to skip using import statements in the timeline.
		if (extensions.fuse!=undefined) _global.Fuse = extensions.fuse;
		if (extensions.fuseFMP!=undefined) extensions.fuseFMP.simpleSetup(); // adds _global.FuseFMP reference
		initialize(MovieClip.prototype, Button.prototype, TextField.prototype);
		if (extensions.shortcuts==undefined) { // ignores OUTPUT_LEVEL since it's crucial
			FuseKitCommon.error('001');
		}
	}
	
	/**
	* An optional setup command that registers additional classes for use with the ZigoEngine.
	* @description	This setup command should only be called once at the beginning of your program. 
	* Use either this or {@link #simpleSetup}, not both. 
	* The difference is that <code>register</code> links additional classes to the engine without altering base prototypes.
	* <pre>import com.mosesSupposes.fuse.*;
	* ZigoEngine.register(PennerEasing, Fuse, FuseFMP);</pre>
	* Note that to keep filesize to a minimum you should only register the features you intend to use. Use publish settings to "omit trace actions" to further reduce filesize.
	* @param classReference		 Pass any of the following classes (all are optional): 
	* <ul><li><code>Shortcuts</code> Enables {@link #doShortcut}, 'easyfunc' callback parsing, and the option to copy / remove shortcuts on any target or prototype manually using {@link #initialize}. See {@link com.mosesSupposes.fuse.Shortcuts}</li>
	* <li><code>PennerEasing</code> Enables shortcut strings like "easeOutQuad" to be used with the engine. See {@link com.mosesSupposes.fuse.PennerEasing}</li>
	* <li><code>Fuse</code> Enables Fuse for animation sequencing. Note that if animation won't be sequenced you do may simply import and use Fuse without ZigoEngine. See {@link com.mosesSupposes.fuse.Fuse}</li>
	* <li><code>FuseFMP</code> Enables shortcut strings like <code>DropShadow_distance</code> to be tweened in the engine. See {@link com.mosesSupposes.fuse.FuseFMP}</li>
	* <li><code>FuseItem</code> Enables Fuse-style Object Syntax to be used with the <code>ZigoEngine.doTween</code>. Note that Fuse does not need to be registered to use this feature. See {@link com.mosesSupposes.fuse.FuseItem}</li></ul>
	*/
	public static function register(classReference:Function):Void
	{
		if (extensions==undefined) extensions = {};
		var supported:String = '|fuse|fuseItem|fuseFMP|shortcuts|pennerEasing|customEasing|';
		for (var i:String in arguments) {
			var key:String = (arguments[i]).registryKey;
			if (extensions[key]==undefined && supported.indexOf('|'+key+'|')>-1) {
				extensions[key] = (arguments[i]); //retain class
				if (key=='fuseFMP' || key=='shortcuts') Object(extensions[key]).initialize(); // not entirely necessary.
			}
		}
	}
	
	/**
	* (Advanced) Prepares targets for use with engine.
	* @description This method is never needed when extending prototypes with <code>simpleSetup</code>. 
	* It can be used to initialize specific targets to accept listeners prior to tweening - see {@link com.mosesSupposes.fuse.ZManager} for an example.
	* If the Shortcuts class was passed to {@link #register}, this method also copies all tweening shortcuts to targets.
	* 
	* @param	One or more targets to initialize.
	* @see #deinitialize
	*/
	public static function initialize(target:Object):Void
	{
		if (arguments.length>0) {
			initializeTargets.apply(ZigoEngine, arguments);
			if (extensions.shortcuts!=undefined) {
				extensions.shortcuts.addShortcutsTo.apply(extensions.shortcuts, arguments);
			}
		}
	}
	
	/** 
	* (Advanced) Clears targets from being used with the engine.
	* @description	Removes AsBroadcaster functionality (and tweening shortcuts if the Shortcuts class was registered) 
	* from any object previously initialized using <code>initialize</code>.<br><br>
	* @param	One or more targets to initialize, or nothing/null to deinitialize base prototypes (for example to undo simpleSetup)
	* @see #initialize
	*/
	public static function deinitialize(target:Object):Void
	{
		if (arguments.length==0 || target==null) {
			arguments.push(MovieClip.prototype, Button.prototype, TextField.prototype);
		}
		deinitializeTargets.apply(ZigoEngine, arguments);
		if (extensions.shortcuts!=undefined) { 
			extensions.shortcuts.removeShortcutsFrom.apply(extensions.shortcuts, arguments);
		}
	}
	
	/**
	* @return	Number set using <code>setUpdateInterval</code>, or <code>undefined</code> if unset. 
	* @see	#setUpdateInterval
	*/
	public static function getUpdateInterval():Number {
		return updateTime;
	}
	
	/**
	* When set, the engine will run on a setInterval pulse instead of a frame pulse.
	* @param time		Pulse duration in milliseconds, or null/undefined to return to an frame-based pulse.
	* @description		In most cases it is best to leave the engine in its default state since a frame-based pulse usually renders more smoothly. 
	* The engine always uses seconds for tween duration so using a longer interval will only reduce animation quality, not slow tweens down. 
	* This may be desirable in some cases, for instance to reduce CPU usage in banners.
	*/
	public static function setUpdateInterval(time:Number):Void {
		if (_playing) {
			setup(true);
			updateTime = time;
			setup();
		}else{
			updateTime = time;
		}
	}
	
	/**
	* Depth of the ZigoEnginePulse clip.
	* @return		numeric depth in _root
	*/
	public static function getControllerDepth():Number { 
		return tweenHolder.getDepth(); 
	}
	
	/**
	* Creates a clip in the _root timeline called "ZigoEnginePulse" or sets its depth
	* @param	 If null or nothing passed the beacon clip is placed at depth 6789, but a depth of 0 will be more convenient if you'll be using depth management in _root.
	*/
	public static function setControllerDepth(depth:Number):Void {
		if (depth==null || _global.isNaN(depth)==true) {
			depth = 6789;
		}
		if(Object(tweenHolder).proof!=null) {
			tweenHolder.swapDepths(depth);
		}
		else {
			tweenHolder = _root.createEmptyMovieClip("ZigoEnginePulse", depth);
		}
	}

	/**
	* An alternative to {@link #doTween} that accepts Shortcut syntax. <b>Requires registration of the Shortcuts class.</b>
	* @description	This idea thanks to Yotam Laufer. Example:
	* <pre>ZigoEngine.doShortcut(my_mc, 'scaleTo', 200, 1, 'easeOutQuad');</pre>
	* See {@link com.mosesSupposes.fuse.ZigoEngine} introduction for instructions on registering Shortcuts to enable this feature.
	* @param targets	 	Tween target object or array of target objects
	* @param methodName	 	The shorcut as a string, such as "alphaTo", followed by parameters that follow that shortcut's format.
	* @return				A comma-delimited string of props successfully added. When multipe targets were passed, a pipe-delimited series is returned to enable verification of individual properties per target.
	*/
	public static function doShortcut(targets:Object, methodName:String):String
	{
		if (extensions.shortcuts==undefined) {
			if (OUTPUT_LEVEL>0) FuseKitCommon.error('002');
			return null;
		}
		return (extensions.shortcuts.doShortcut.apply(extensions.shortcuts, arguments));
	}
	
	/**
	* Generates and immediately begins one or more property-tweens running on one or more targets.
	* @description	<pre>ZigoEngine.doTween(my_mc, '_x,_y', [100,150], 1, Strong.easeInOut);</pre>
	* {@link com.mosesSupposes.fuse.Fuse}-style Object Syntax may also be used if the {@link com.mosesSupposes.fuse.FuseItem} class is registered:
	* <pre>ZigoEngine.doTween({ target:my_mc, start_alpha:0, y:150, ease:Strong.easeInOut });</pre>
	* @param targets		Tween target object or array of target objects<br>
	* (<i>All</i> properties listed in the following parameter are tweened on <i>all</i> targets specified.)
	* 
	* @param props			String like <code>"_x"</code>, comma-delimited list of properties like <code>"_x,_y"</code>, or Array of properties like <code>["_x","_y"]</code>.
	* <br>The engine accepts any existing property in the target including custom variables, and the following special properties:
	* <ul>
	* <li><code><b>_bezier_</b></code> Object  <b><code>{x:,y:,controlX:,controlY:}</code></b> generates a curved motion path.
	*   <ul>
	* 	<li>Relative (string) values supported for all parameters</li>
	* 	<li>Only two properties are needed to tween a curve</li>
	* 	<li>Example, slides right / arcs up:<br> 
	* 	 <code>ZigoEngine.doTween(clip1, <b>"_bezier_", {x:"100",controlY:"-50"}</b>);</code></li>
	*   </ul>
	* </li>
	* <li><code><b>_brightness</b></code> -100=black, 0=normal, 100=white</li>
	* <li><code><b>_brightOffset</b></code> Burn effect. -100=black, 0=normal, 100=white</li>
	* <li><code><b>_colorReset</b></code> 100 = fully restores target's colors to normal.</li>
	* <li><code><b>_colorTransform</b></code> Generic object in Flash7 transform format: <b><code>{ra:,rb:,etc.}</code></b></li>
	* <li><code><b>_contrast</b></code> 0=gray, 100=normal, 200=high-contrast, higher=posterized</li>
	* <li><b><code>_fade</code></b> Like <span class="code"><b>_alpha + _visible</b></span>. Typically used with 0 or 100 values.
	*   <ul>
	* 	<li>Visibility turned off when tween ends if value is under 50</li>
	* 	<li>Visibility turned on when any <span class="code">_fade</span> tween starts </li>
	*   </ul>
	* </li>
	* <li><code><b>_frame</b></code> Tweens a target MovieClip's timeline to a frame, with easing.</li>
	* <li><code><b>_invertColor</b></code> 100 = Photo-negative effect</li>
	* <li><code><b>_scale</b></code> Sets <span class="code">_xscale</span> and <span class="code">_yscale</span> to the same value.</li>
	* <li><code><b>_size</b></code> Sets <span class="code">_width</span> and <span class="code">_height</span> to the same value.</li>
	* <li><code><b>_tint</b></code> Accepts various formats:
	*   <ul>
	* 	<li><span class="code">0x000000</span> and <span class="code">"#000000"</span> hex formats</li>
	* 	<li> <span class="code">null</span> (full color reset)</li>
	* 	<li>Object with  tint &amp; percent properties:<br> 
	* 	<code><b>{tint:</b>Number/null/hexString<b>, percent:</b>Number/String<b>}</b></code>.</li>
	*   </ul>
	* </li>
	* <li><code><b>_tintPercent</b></code> Value range 0-100</li>
	* </ul>
	*	When {@link com.mosesSupposes.fuse.FuseFMP} is registered, a large number of BitmapFilter properties are tweenable:
	*	<ul><li><code>Blur_blurX, etc.</code> Format follows the convention short-filtername+"_"+filter property.</li></ul>
	* 
	* @param endvals		tween end-value or Array of corresponding end-values. A single end-value can be used with multiple properties.<br>
	* Accepts various formats:<br>
	* <ul><li><b>Number</b> A normal absolute end-value. Tweening _x to 10 in the main timeline moves it to 10px from the left edge of the stage.</li>
	* <li><b>String - Relative values:</b> Passing a string version of a number like "10" or "-10" calculates end-value as relative 
	* to the start position of the tween.<br>Examples: Tweening _x to "10" moves the clip 10px to the right of its current position.<br>Tweening _rotation to a 
	* negative string value like "-90" affects a counter-clockwise spin.</li>
	* <li><b>Bezier, tint, or color-transform object</b> See <code>_bezier_, _colorTransform, _tint</code> properties above.</li>
	* <li><b>Multi-value Object or Array</b> - (Advanced) A new feature is the ability to directly tween multiple values in an Object or Array. 
	* Note that like any custom variables these objects must exist prior to tweening and have their properties set to numerical values in advance.<br>
	* <code>var myObj:Object = {x:0,y:0,z:0}; ZigoEngine.doTween(this, "myObj", { x:1, y:2, z:3 });</code><br>
	* <br>Note also that because this parameter already accepts an Array for multiple end-values, you must wrap it in a second Array:<br> 
	* <code>var myArray:Array = [ 0, 0 ]; ZigoEngine.doTween(this, "myArray", [[10,20]]);</code></li>
	* <li><b>Colors Array</b> - (Advanced) Tweening a generic array of color values can help with situations like tweening the properties of a gradient fill
	* that's redrawn on tween update. Any array whose name contains 'colors' (case is ignored) will be handled by the engine as an array of color values. 
	* Note that the internal colortransforms are not applied to any target, simply updated within the array.<br>
	* Example: <code>ZigoEngine.doTween(this, "myColors", [[ 0x000000, 0xFFFFFF ]], 1, null, 0, { scope:this, updfunc:'redrawGradient' });</code></li>
	* </ul>
	* <br>
	* (advanced) Example of tweening a Matrix object to move and skew a clip (Flash 8 required):
	* <pre>import com.mosesSupposes.fuse.*;
	* import flash.geom.Matrix;
	* import flash.geom.Transform;
	* ZigoEngine.register(PennerEasing);
	* var myMatrix:Matrix = new Matrix();
	* var boxTrans:Transform = new Transform(box);
	* function applyMatrixTrans():Void { boxTrans.matrix = myMatrix; }
	* ZigoEngine.doTween(	this, "myMatrix", {a:.5, c:.5, tx:200 },
	* 						1, 'easeOutBounce', 0, {updfunc:applyMatrixTrans});</pre>
	* 
	* @param seconds		tween duration. If nothing is passed, defaults to <code>ZigoEngine.DURATION</code>.
	* 
	* @param ease			Accepts a number of formats based on which features are registered:
	* <ul><li>function - like <code>mx.transitions.easing.Strong.easeInOut</code></li>
	* <li>shortcut-string - <code>"easeInOutQuint"</code> or any other function name from {@link com.mosesSupposes.fuse.PennerEasing}</li>
	* <li>Array generated by the Custom Easing Tool. (This special panel is installed into Flash when you install the Fuse Kit v2.1 or later MXP extension). Note that the {@link com.mosesSupposes.fuse.CustomEasing} class must be registered to use this feature.</li>
	* <li>null or nothing - defaults to <code>ZigoEngine.EASING</code> if set, or PennerEasing.easeOutQuint, which is hardcoded in the engine as a default fallback.</li>
	* </ul>
	* 
	* @param delay			seconds to wait before performing the tween. Start callback and <code>onTweenStart</code> event are fired at end of delay. 
	* 
	* @param callback		function, string, or object
	* <br><br>
	* The kit tries to parse callbacks in many formats. Note that for callbacks to execute successfully in many cases it is crucial that 
	* a "this" scope is defined in which to locate and fire the function. Although the engine often successfully locates your callbacks, 
	* the recommended option is <b>Callback Object,</b> which is the most stable and flexible, demands the least parsing, and allows you 
	* to most clearly define scope, as well as providing additional tween options.
	* <br>
	* <ol>
	* <li><b>Function</b>
	* <br>
	* <code>ZigoEngine.doTween(mc,"_x",100,1,"linear",0, myCallback);</code>
	* <ul><li>Reference: <code>myCallback</code></li>
	* <li>String: <code>"myCallback"</code></li>
	* <li>Inline: <code>function(){ ... }</code></li>
	* <li>Delegate: <code>mx.utils.Delegate.create(....)</code> - adds scope</li>
	* </ul>
	* </li>
	* <li><b>Easyfunc String</b> <em>(Shortcuts must be registered to use this feature)</em>
	* <br>
	* <code>ZigoEngine.doTween(mc,"_x",100,1,"linear",0, "this.myCallback(true);");</code>
	* <ul><li>example: <code>"trace('The tween is finished');"</code></li>
	* <li>Supports complex scope and many datatypes for argument params:<br> 
    * <code>"myscope.myscope.myfunc(true,1,'hello',{paramA:1,paramB:false,[0,1],null);"</code></li>
	* <li>You may also use easyfunc strings in callback objects (below) for start, update and end callbacks.</li>
	* <li><li><i>Limitations:</i> Easyfunc strings are <em>not</em> a good option for class authoring. They work well when coding in frames of the _root timeline 
	* and enhance the Shortcuts paradigm. When a callback resides in a frame of a subclip's timeline, the easyfunc string should contain an absolute path to the 
	* function. For instance if clip1 exists in the _root timeline and houses the function myCallback, use <code>"clip1.myCallback();"</code>.
	* <br><br>
	* A somewhat impractical workaround for class authors is to set a local reference like <code>var t:MyClass=this;</code> preceding an easyfunc like 
	* <code> "t.myMethod();"</code>, which exploits scope-chain during <i>eval</i>. Again, Callback Objects are recommended for OO coders.</li>
	* </ul>
	* </li>
	* <li><b>Callback Object</b>
	* <code>ZigoEngine.doTween(clip1,"_x","100",1,"easeOutQuad",0, {scope:this, func:"myCallback", args:true});</code><br>
	* <code>ZigoEngine.doTween(clip2,"_x","100",1,"easeOutQuad",0, { cycles:2 }); // yoyo back once</code>
	* <ul>
	* <li><code>func</code> Function, string name of function, or Easyfunc string like <code>"myClip.doSomething(true);"</code> ({@link com.mosesSupposes.fuse.Shortcuts} must be registered to use the Easyfunc feature.)</li>
	* <li><code>scope</code> The "this" object in which to locate and fire the callback. Not always required but recommended if the engine cannot locate the callback or fires the wrong function.</li>
	* <li><code>args</code> One argument or an array of arguments to pass to the <code>func</code> callback.</li>
	* <li><code>startfunc</code> Callback fired after any delay and as tween is starting. Supports various formats - see func above.</li>
	* <li><code>startscope</code> Specific scope for the <code>startfunc</code> callback. If not defined, the <code>scope</code> property will be used.</li>
	* <li><code>startargs</code> One argument or an array of arguments to pass to the <code>startfunc</code> callback.</li>
	* <li><code>updfunc</code> Callback fired on engine pulse as the tweens in the action are updated. Accepts various formats - see func above.</li>
	* <li><code>updscope</code> Specific scope for the <code>updfunc</code> callback. If not defined, the <code>scope</code> property will be used.</li>
	* <li><code>updargs</code> One argument or an array of arguments to pass to the <code>updfunc</code> callback.</li>
	* </ul>
	* <br>
	* <b>Additional callback object parameters</b>
	* <ul><li><code>cycles</code> Tweens back and forth between start and end.<br>
	* 0 or "LOOP" = infinite cycles, default = 1, 2 or more to specify cycles.</li>
	* <li><code>skipLevel</code> 0,1, or 2. An advanced behavior setting for cases where tweens fail. See {@link #SKIP_LEVEL} for details.<br>
	* Including this paramter in a callback object overrides the engine default on a per-tween basis.</li>
	* <li><code>extra1</code> Optional fifth parameter sent to easing method. Elastic easing amplitude or Back easing overshoot.</li>
	* <li><code>extra2</code> Optional sixth parameter sent to easing method. Elastic easing period.</li>
	* <li><code>roundResults</code> Overrides the class setting {@link #ROUND_RESULTS} for an individual tween. 
	* Useful for instance, if the class default is true but you need to execute a tween such as DropShadow_alpha which requires a 0-1 range.</li>
	* <li><span style="text-decoration:line-through"><code>easyfunc</code></span> Removed from kit. <code>func, startfunc, updfunc</code> parameters now accept easyfunc strings (see func above).</li>
	* </ul>
	* </li></ol>
	* 
	* 
	* @return	A formatted string:<br>
	* The engine reports which properties have been added to its active tween list by returning a comma-delimited string of just the properties that were successfully added, such as <code>"_x"</code> or <code>"_x,_y"</code>. 
	* These may occasionally differ from what was tweened, such as <code>"_width,_height"</code> when <code>"_size"</code> was tweened.<br><br>
	* If multiple targets are passed to the engine, a pipe-delimited series of properties is returned in target order, which enables granular review of whether specific properties for each target.<br>
	* <pre>var results:String = ZigoEngine.doTween([clip1,clip2,clip3],"_scale",100,null,0,{skipLevel:1});
	* // results: "_xscale,_yscale||_xscale,_yscale"
	* // because clip2's scale was already set to 100 and the skipLevel is set to skip no-change tweens.</pre>
	*/
	public static function doTween(targets:Object, props:Object, endvals:Object, seconds:Number, ease:Object, delay:Number, callback:Object):String  
	{
		if (extensions.fuse.addBuildItem(arguments)==true) return null; // used by Fuse Simple Syntax
		if (TIME_MULTIPLIER!=prevTimeMult) {
			TIME_MULTIPLIER = Math.abs(TIME_MULTIPLIER);
			if (_global.isNaN(TIME_MULTIPLIER)==true) {
				TIME_MULTIPLIER = 1;
			} // enable trace output for rejected values as well to show that it's at 100%.
			if (OUTPUT_LEVEL>0) {
				FuseKitCommon.error('016',TIME_MULTIPLIER);
			}
			prevTimeMult = TIME_MULTIPLIER;
		}
		// initialize + setup (ZManager singleton required prior to parse)
		if (instance==undefined || (Object(tweenHolder).proof==undefined && updateTime==undefined)) {
			if (MovieClip.prototype.tween!=null && typeof _global.$tweenManager=='object') {
				FuseKitCommon.error('003'); // ignores OUTPUT_LEVEL since this is crucial
			}
			instance = new ZManager();
			_playing = false;
		}
		// targets & properties - make use of ZManager's parser which converts both to arrays. Final argument retains "_fade" property which is handled by ZManager.addTween.
		var params:Object = instance.paramsObj(targets, props, endvals, true);
		var ta:Array = ((params.tg[0]==null || params.tg.length==0) ? undefined : params.tg);
		if (params.pa==undefined || ta==undefined || arguments.length<3) {
			if (extensions.fuseItem!=null && arguments.length==1 && typeof arguments[0]=='object') { //  && typeof ta[0]=='object') {
				return extensions.fuseItem.doTween(arguments[0]); // Route to FuseItem if Obj Syntax
			}
			if (OUTPUT_LEVEL>0) {
				if (arguments.length<3) FuseKitCommon.error('004',
															(arguments.length==1 && arguments[0]==null)
															? '1 (null)'
															: (String(arguments.length)),
															Boolean(extensions.fuseItem==null));
				else FuseKitCommon.error('005',ta.toString(),(params.pa).toString());
			}
			return null;
		}
		if (_playing!=true) {
			setup();
		}
		
		// duration
		if (seconds==null || _global.isNaN(seconds)==true) seconds = (DURATION || 1);
		else if (seconds<0.01) seconds = 0;
		seconds *= TIME_MULTIPLIER;
		
		// delay
		if (delay<0.01 || delay==null || _global.isNaN(delay)==true) delay = 0;
		delay *= TIME_MULTIPLIER;
		
		// callbacks (leave before easing)
		var validCBs:Object = (FuseKitCommon.parseCallback(callback,ta,OUTPUT_LEVEL,true)); // throws its own errors, returns undefined if not valid.
		
		// easing
		var eqf:Function;
		if (typeof ease=='function') {
			if (typeof (Function(ease).call(null,1,1,1,1))=='number') eqf = Function(ease);
			else if (OUTPUT_LEVEL>0) FuseKitCommon.error('014',ease);
		}
		else if (ease==null || ease=='') {
			if (EASING instanceof Function) eqf = Function(EASING);
			else if (extensions.pennerEasing!=undefined) ease = EASING;
		}
		if (typeof ease=='string' && ease!='') {
			if (extensions.pennerEasing[ease]!=undefined) eqf = extensions.pennerEasing[ease];
			else if (OUTPUT_LEVEL>0) FuseKitCommon.error('006',ease);
		}
		else if (ease instanceof Array) {// array from custom easing tool (updated in kit 2.1)
			if (extensions.customEasing!=undefined) {
				validCBs.extra1 = ease;
				if (typeof ease[0]=='number') eqf = extensions.customEasing.precalced;
				else eqf = extensions.customEasing.fromCurve;
			}
			else if (OUTPUT_LEVEL>0) FuseKitCommon.error('015',ease);
		}
		if (typeof eqf!='function'){ // fallback default: easeOutQuint
			eqf = (function (t:Number, b:Number, c:Number, d:Number):Number { return c*((t=t/d-1)*t*t*t*t + 1) + b; });
		}
		// Added the onTweenAdd event in v2.1.3
		if ((ZigoEngine['_listeners']).length>0) {
			ZigoEngine['broadcastMessage'].call(ZigoEngine, 'onTweenAdd', ta, params.pa, params.va, seconds, eqf, delay, validCBs);
		}
		// init each target & add tweens
		var propsAdded:String = '';
		for (var i:String in ta) {
			var o:Object = ta[i];
			if (o.__zigoID__==null) {
				initializeTargets(o); // initializes AsBroadcaster and adds __zigoID__
			}
			else if (instance.getStatus('locked',o)==true) {
				if (OUTPUT_LEVEL>0) FuseKitCommon.error('007',((o._name!=undefined)?o._name:(o.toString())),(params.pa).toString());
				continue;
			}
			//ZManager.addTween(obj:Object, props:Array, endvals:Array, seconds:Number, ease:Function, delay:Number, callback:Object):String
			var pStr:String = (instance.addTween(o, params.pa, params.va, seconds, eqf, delay, validCBs));
			propsAdded = (((pStr==null)?'|':pStr+'|')+propsAdded);
		}
		propsAdded = propsAdded.slice(0,-1);
		return ((propsAdded=='' || propsAdded=='|') ? null : propsAdded);
	}
	
	/**
	* Remove specific or all tweening properties from specific or all tweening targets in engine.
	* @usage <pre>// stop any tweens running in clip0
	* ZigoEngine.removeTween(clip0);
	* 
	* ZigoEngine.doTween(clip1, "_x, _xscale, _alpha", ["100", 200, 0], 1, "easeInOutExpo");
	* // during tween, kill off just the slide and scale but allow the fade-out to run:
	* ZigoEngine.removeTween(clip1, "_x, _scale");
	* 
	* // kill all tweens in multiple targets
	* ZigoEngine.removeTween([clip2,clip3,clip4]);</pre>
	* The <code>onTweenInterrupt</code> event is fired by the engine when this method is used (see {@link #addListener} for more info).
	* @param targs		a single target object, array of targets, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @param props		a property string, array of property strings, null or nothing for all props, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	*/
	public static function removeTween (targs:Object, props:Object):Void {
		instance.removeTween(targs, props);
	}
	
	/**
	* Test if a target and optionally a specific property is being handled by the engine.
	* @param targ		a single target object to test
	* @param prop		a specific property string
	* @return			true if a matching active tween is found, which may be paused or playing 
	*/
	public static function isTweening(targ:Object, prop:String):Boolean {
		return Boolean(instance.getStatus('active',targ,prop));
	}
	
	/**
	* Returns the number of tweens active in a target object.
	* @param targ		target tween passed to determine if active, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @return			number of active tweens, which may be paused or playing
	*/
	public static function getTweens(targ:Object):Number {
		if (instance==undefined) return 0;
		return Number(instance.getStatus('count',targ));
	}
	
	/**
	* Locks a target to prevent tweens from running until target is unlocked.
	* @description A warning message is thrown if your program attempts to call a tween on a locked target.
	* @usage Accepts only one target at a time.<br><br>
	* {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} is not accepted by lockTween, because that would only affect targets currently being tweened in the engine. 
	* (In a case where you want to stop or pause all running tweens use <code>pauseTween(FuseKitCommon.ALL)</code> or <code>removeTween(FuseKitCommon.ALL)</code>. 
	* The lockTween method is used to preset targets that usually are not currently being tweened in the engine. For more complex scenarios you should build an array 
	* of targets you need to affect, then use a for-loop to call the method on each one individually.
	* <pre>// example of how you could manage a block of targets in your program with lock/unlock
	* var lockableTargs:Array = [clip1,clip2,clip5];
	* function toggleTweenLock(setLocked:Boolean):Void {
	* 	for (var i:String in lockableTargs) ZigoEngine.lockTween(lockableTargs[i], setLocked);
	* }</pre>
	* 
	* @param targ		Object to lock
	* @param setLocked	locked value
	* @see #pauseTween
	* @see #removeTween
	*/
	public static function lockTween(targ:Object, setLocked:Boolean):Void {
		instance.alterTweens('lock',targ,(setLocked==true));
	}
	
	/**
	* Locks tweens and prevents from running until tween is unlocked.
	* @param targ		Object to lock
	* @return 			locked value
	*/
	public static function isTweenLocked(targ:Object):Boolean {
		return Boolean(instance.getStatus('locked',targ));
	}
	
	/**
	* Fast-forwarding a tween ends it and removes it from the engine. 
	* @usage <pre>ZigoEngine.doTween(clip1, "_x, _xscale, _alpha", ["100", 200, 0], 1, "easeInOutExpo");
	* // during tween, fast-forward just the slide and scale but allow the fade-out to run:
	* ZigoEngine.ffTween(clip1, "_x, _scale");
	* 
	* // fast-forward all tweens in multiple targets
	* ZigoEngine.ffTween([clip2,clip3,clip4]);</pre>
	* @param targs				a single target object, array of targets, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @param props				a property string, array of property strings, null or nothing for all props, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	* @param suppressEndEvents	if true is not passed, engine will fire 'onTweenEnd' event and any end-callbacks associated with the tween
	*/
	public static function ffTween(targs:Object, props:Object, suppressEndEvents:Boolean):Void {
		instance.alterTweens('ff',targs,props,null,suppressEndEvents);
	}
	
	/**
	* Jumps a tween to a specific point in its duration.
	* @description	Results vary dramatically based on the easing style used.
	* @usage <pre>// jump to halfway through a 2-second tween
	* ZigoEngine.skipTweenTo(1, clip1);</pre>
	* @param seconds	amount of time within the tween duration to jump to (for instance, in a 1.5-second tween, .75 jumps to the halfway point).
	* @param targs		a single target object, array of targets, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @param props		a property string, array of property strings, null or nothing for all props, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	*/
	public static function skipTweenTo(seconds:Number, targs:Object, props:Object):Void {
		instance.alterTweens('skipTo',targs,props,false,false,seconds);
	}
	
	/**
	* Rewinds and either pauses or restarts one or more tweens
	* @usage <pre>ZigoEngine.doTween(clip1, "_x, _xscale, _alpha", ["100", 200, 0], 1, "easeInOutExpo");
	* // during tween, rewind just the slide and scale but allow the fade-out to run:
	* ZigoEngine.rewTween(clip1, "_x, _scale");
	* 
	* // rewind and pause all tweens in several targets
	* ZigoEngine.rewTween([clip2,clip3,clip4], null, true);
	* 
	* // You may not want start callbacks and/or events to re-fire on rewind.
	* // These can be suppressed using the 4th parameter as in this example.
	* var listenerObj:Object = new Object();
	* listenerObj.onTweenStart = function(o:Object):Void {
	* 	trace(o.target+" start Event, props started: "+o.props);
	* };
	* ZigoEngine.initialize(clip5); // prepares clip to add a listener
	* clip5.addListener(listenerObj);
	* ZigoEngine.doTween(clip5, "_x", "100", 3, "easeInOutBack", 0,
	* 						{startfunc:function(){trace("Start Callback!");}});
	* function onMouseDown() {
	* 	// click the stage to restart the animation before it ends.
	* 	// the events are not refired.
	* 	ZigoEngine.rewTween(clip5, null, false, true);
	* }</pre>
	* @param targs		a single target object, array of targets, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @param props		a property string, array of property strings, null or nothing for all props, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	* @param pauseFlag	true to rewind-and-pause
	* @param suppressStartEvents	if true is not passed, engine will refire 'onTweenStart' event and any start callbacks associated with the tween
	*/
	public static function rewTween(targs:Object, props:Object, pauseFlag:Boolean, suppressStartEvents:Boolean):Void {
		instance.alterTweens('rewind',targs,props,pauseFlag,suppressStartEvents);
	}
	
	/**
	* Test whether any or a specific property is paused in a target object
	* @usage <pre>if (ZigoEngine.isTweenPaused(clip1,"_alpha")==true) { ... }</pre>
	* @param targ		a single target object to test
	* @param props		a property string, null or nothing for any property, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	* @return			paused value
	*/
	public static function isTweenPaused(targ:Object, prop:String):Boolean {
		return Boolean(instance.getStatus('paused',targ,prop));
	}
	
	/**
	* Pause one or more tweens
	* @usage <pre>ZigoEngine.doTween(clip1, "_x, _xscale, _alpha", ["100", 200, 0], 1, "easeInOutExpo");
	* // during tween, pause just the slide and scale but allow the fade-out to run:
	* ZigoEngine.pauseTween(clip1, "_x, _scale");
	* 
	* // pause all engine tweens in the swf
	* ZigoEngine.pauseTween(FuseKitCommon.ALL);</pre>
	* @param targs		a single target object, array of targets, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @param props		a property string, array of property strings, null or nothing for all props, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	*/
	public static function pauseTween(targs:Object, props:Object):Void {
		instance.alterTweens('pause',targs,props);
	}
	
	/**
	* Legacy - see {@link #resumeTween}
	*/
	public static function unpauseTween(targs:Object, props:Object):Void {
		instance.alterTweens('unpause',targs,props);
	}
	
	/**
	* Unpause one or more tweens.
	* @usage <pre>ZigoEngine.resumeTween(clip1);
	* 
	* // resume all engine tweens in the swf
	* ZigoEngine.resumeTween(FuseKitCommon.ALL);</pre>
	* @param targs		a single target object, array of targets, or {@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for every active target
	* @param props		a property string, array of property strings, null or nothing for all props, {@link com.mosesSupposes.fuse.FuseKitCommon#ALLCOLOR} for any active color transform
	*/
	public static function resumeTween(targs:Object, props:Object):Void {
		instance.alterTweens('unpause',targs,props);
	}
	
	
	// -------------------------------------------------------------------------------------
	// - Flash7 Color Helpers - You may find these useful any time, not just when tweening.
	// (thanks goes out to R. Penner for most of the color math here)
	// -------------------------------------------------------------------------------------
	
	/**
	 *  (General) Color-transforms a target by keyword.
	 *  @description	Example: <code>ZigoEngine.setColorByKey(my_mc, 'tint', 50, 0x33FF00);</code>
	 *  @param targetObj	MovieClip or target to alter
	 *  @param type			String <code>"brightness", "brightOffset", "contrast", "invertColor", or "tint"</code>
	 *  @param amt			Percentage, can be negative in some cases
	 *  @param rgb			For "tint", a color value in 0x000000 or "#000000" format
	 */
	public static function setColorByKey(targetObj:Object, type:String, amt:Number, rgb:Object):Void {
		(new Color(targetObj)).setTransform(getColorTransObj(type,amt,rgb));
	}
	
	/**
	 *  (General) Generates a generic Flash7-style color-transform object with props like ra, etc., by keyword.
	 *  @param type			String <code>"brightness", "brightOffset", "contrast", "invertColor", or "tint"</code>
	 *  @param amt			Percentage, can be negative in some cases
	 *  @param rgb			For "tint", a color value in 0x000000 or "#000000" format
	 */
	public static function getColorTransObj(type:String, amt:Number, rgb:Object):Object {
		switch (type) {
		 case 'brightness' : // amt:-100=black, 0=normal, 100=white
			var percent:Number = (100-Math.abs(amt));
			var offset:Number = ((amt>0) ? (255*(amt/100)) : 0);
			return {ra:percent, rb:offset, ga:percent, gb:offset, ba:percent, bb:offset};
		 case 'brightOffset' : // "burn" effect. amt:-100=black, 0=normal, 100=white
			return {ra:100, rb:(255*(amt/100)), ga:100, gb:(255*(amt/100)), ba:100, bb:(255*(amt/100))};
		 case 'contrast' : // amt:0=gray, 100=normal, 200=high-contrast, higher=posterized.
			return {ra:amt, rb:(128-(128/100*amt)), ga:amt, gb:(128-(128/100*amt)), ba:amt, bb:(128-(128/100*amt))};
		 case 'invertColor' : // amt:0=normal,50=gray,100=photo-negative
			return {ra:(100-2*amt), rb:(amt*(255/100)), ga:(100-2*amt), gb:(amt*(255/100)), ba:(100-2*amt), bb:(amt*(255/100))};
		 case 'tint' : // amt:0=none,100=solid color (>100=posterized to tint, <0=inverted posterize to tint)
		 	if (rgb!=null) {
		 		var rgbnum:Number;
				if (typeof rgb=='string') {// Hex strings are not interpreted as relative values like other color props. Allow strings like "#FFFFFF" or "FFFFFF"
					if (rgb.charAt(0)=='#') rgb = rgb.slice(1);
					rgb = ((rgb.charAt(1)).toLowerCase()!='x') ? ('0x'+rgb) : (rgb);
				}
				rgbnum = Number(rgb);
				return {ra:(100-amt), rb:(rgbnum >> 16)*(amt/100), ga:(100-amt), gb:((rgbnum >> 8) & 0xFF)*(amt/100), ba:(100-amt), bb:(rgbnum & 0xFF)*(amt/100)};
			}
		}
		return {rb:0, ra:100, gb:0, ga:100, bb:0, ba:100}; // full reset
	};

	/**
	*  (General) Provides readings by keyword for a target object or Flash7-style color-transform object.
	*  @description	Inherent rounding errors are common! Especially when percentages are below 50. Even .tintString hex values may differ slightly.
	*  @param targOrTransObj	target object or Flash7-style color-transform object with props like ra, etc.
	*  @return					object may contain props brightness, brightOffset, contrast, invertColor, tint, tintPercent, and tintString
	*/
	public static function getColorKeysObj(targOrTransObj:Object):Object {
		var trans:Object = (targOrTransObj.ra!=undefined) ? targOrTransObj : (new Color(targOrTransObj)).getTransform();
		var sim_a:Boolean = (trans.ra==trans.ga && trans.ga==trans.ba);
		var sim_b:Boolean = (trans.rb==trans.gb && trans.gb==trans.bb);
		var o:Object = { tintPercent : Number( (sim_a==true) ? (100 - trans.ra) : 0 ) };
		if (o.tintPercent!=0) {
			var ratio:Number = 100/o.tintPercent;
			o.tint = ((trans.rb*ratio)<<16 | (trans.gb*ratio)<<8 | trans.bb*ratio);
			var hexStr:String = o.tint.toString(16);
			var toFill:Number = 6 - hexStr.length;
			while (toFill-->0) hexStr = '0' + hexStr;
			o.tintString = '0x'+hexStr.toUpperCase();
		}
		if (sim_a==true && sim_b==true) {
			if (trans.ra<0) o.invertColor = (trans.rb * (100/255));
			else if (trans.ra==100 && trans.rb!=0) o.brightOffset =(trans.rb * (100/255));
			if (trans.ra!=100) {
				if ((trans.rb==0 || (trans.rb!=0 && (255*((100-trans.ra)/100))-trans.rb <= 1))) { // <=1:rounding error correct
					o.brightness = ((trans.rb!=0) ? (100-trans.ra) : (trans.ra-100));
				}
				if ((128-(128/100*trans.ra))-trans.rb <= 1) o.contrast = trans.ra; // <=1:rounding error correct
			}
		}
		return o;
	}
	
	/**
	 * @exclude
	 * Internal method that prepares any number of targets with AsBroadcaster functionality and a hidden engine ID.
	 */
	public static function initializeTargets():Void
	{
		for (var i:String in arguments) {
			var obj:Object = arguments[i];
			// this catches mc/btn/tf prototypes, which should not be directly initialized. However other class prototypes will not be caught and may result in recursion errors.
			// Please let me know if there is a way (f7 compatible) to detect whether an object is a prototype or not!
			if (obj==MovieClip.prototype || obj==Button.prototype || obj==TextField.prototype || obj==Object.prototype) {
				if (obj.oldAddListener==undefined) {
					if (obj==TextField.prototype) {
						obj.oldAddListener = obj.addListener; // TextField class is already initialized, this prevents recursion errors
						_global.ASSetPropFlags(obj, 'oldAddListener', 7, 1);
					}
					obj.addListener = function(o:Object):Void { // (this bit is only used if simpleSetup is called and addListener is called on a target before tweening it.)
						if ((this).__zigoID__==undefined) {
							ZigoEngine.initializeTargets((this));
						}
						if ((this) instanceof TextField) {
							Function((this).oldAddListener).call((this),o);// workaround: flash mc & tf behavior differs
						}
						else (this).addListener(o);
					};
					if (obj==MovieClip.prototype) { // hides the fake-in method above from for-in loops and deletion.
						_global.ASSetPropFlags(obj, 'addListener', 7, 1);
					}
				}
			}
			else if (obj.__zigoID__==undefined) {
				obj.__zigoID__ = zigoIDs;/*	although this is intrusive (in the same way AsBroadcaster or EventDispatcher is),
					  it's faster & safer than storing a reference list which can impair garbage collection and lead to bloat. */
				_global.ASSetPropFlags(obj, '__zigoID__', 7, 1);
				zigoIDs++;
				if (obj._listeners==null || obj.addListener==null) {
					AsBroadcaster.initialize(obj); // instances
				}
			}
		}
	}
	
	/**
	 * @exclude
	 * Internal method that strips AsBroadcaster functionality and hidden engine ID from any target.
	 */
	public static function deinitializeTargets():Void
	{
		for (var i:String in arguments) { 
			var obj:Object = arguments[i];
			if (obj.__zigoID__!=undefined) {
				_global.ASSetPropFlags(obj, '__zigoID__,_listeners,broadcastMessage,addListener,removeListener', 0, 2); // 0,2 is NOT a mistake, do not change
				delete obj.__zigoID__;
				delete obj._listeners;
				delete obj.broadcastMessage;
				delete obj.addListener;
				delete obj.removeListener;
			}
			if (obj.oldAddListener!=undefined) { // reset textfield prototype to prior addListener method.
				_global.ASSetPropFlags(obj, 'oldAddListener', 0, 2);
				obj.addListener = obj.oldAddListener;
				delete obj.oldAddListener;
			}
		}
	}
	
	/**
	 * @exclude
	 * Internal relay for use by ZManager instance only
	 * @param inst			ZManager instance
	 * @param deinitFlag	true stops engine
	 */ 
	public static function __mgrRelay(inst:ZManager,method:String,args:Array):Void
	{
		if (inst==instance) {
			Function(ZigoEngine[method]).apply(ZigoEngine,args);
		}
	}
	
	// ---------------------------------------------------------------------------------
	// -- Private ----------------------------------------------------------------------
	// ---------------------------------------------------------------------------------

	/**
	* Internal method that initializes the engine to start or stop executing updates on a pulse
	* @param deinitFlag		true to stop engine
	*/
	private static function setup(deinitFlag:Boolean):Void 
	{
		// deinit
		if (deinitFlag==true) {
			_playing = false;
			clearInterval(updateIntId);		
			delete tweenHolder.onEnterFrame;
			return;
		}
		// init
		instance.cleanUp();
		clearInterval(updateIntId);
		delete updateIntId;
		if(updateTime!=null && updateTime>0) {
			updateIntId = setInterval(instance, 'update', updateTime);
		}
		else {
			if(Object(tweenHolder).proof==null) { // fixes bug with "Simulate Download" (tweenHolder is still movieclip, but not on the stage)
				setControllerDepth(6789); // creates tweenHolder
				Object(tweenHolder).proof = 1;
			}
			var _inst:ZManager = instance;
			tweenHolder.onEnterFrame = function() {
				_inst.update.call(_inst);
			};
		}
		_playing = true;
		instance.now = getTimer();
	}
}